package com.punai.gk.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.multi.ListValueMap;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.punai.common.core.domain.CommonConstants;
import com.punai.common.core.domain.TreeBo;
import com.punai.common.core.text.Convert;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.SecurityUtils;
import com.punai.gk.domain.GkItem;
import com.punai.gk.domain.GkUseData;
import com.punai.gk.domain.bo.GkTreeList;
import com.punai.gk.domain.bo.GkUserDataBo;
import com.punai.gk.domain.constants.GkConstants;
import com.punai.gk.domain.vo.GkUseDataItemVo;
import com.punai.gk.domain.vo.GkUseDataVo;
import com.punai.gk.mapper.GkUseDataMapper;
import com.punai.gk.service.IGkTemplateService;
import com.punai.gk.service.IGkUseDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 归口数据Service业务层处理
 *
 * @author ruoyi
 * @date 2023-01-06
 */
@Service
public class GkUseDataServiceImpl extends ServiceImpl<GkUseDataMapper,GkUseData> implements IGkUseDataService
{
    @Autowired
    private GkUseDataMapper gkUseDataMapper;
    @Autowired
    private IGkTemplateService iGkTemplateService;

    /**
     * 新增归口数据
     *
     * @param vo 归口数据
     * @return 结果
     */
    @Override
    @Transactional
    public int insertGkUseData(GkUseDataVo vo)
    {
        String templateId = vo.getTemplateId();
        String pid = vo.getPid();
        List<GkUseDataItemVo> itemVos = vo.getItemVos();
        List<GkUseData> gkUseDataList = new ArrayList<>();
        String linkId = IdUtil.simpleUUID();

        // 生成id pid 对象数据
        GkUseData gkdId = new GkUseData();
        gkdId.setId(linkId);
        gkdId.setLinkId(linkId);
        gkdId.setCodeDesc(GkConstants.GK_DEF_COLUMN.ID.getCodeDesc());
        gkdId.setNameStr(GkConstants.GK_DEF_COLUMN.ID.getNameDesc());
        gkdId.setValueStr(linkId);
        gkdId.setTemplateId(templateId);
        gkdId.setCompanyId(SecurityUtils.getCompanyId());
        gkUseDataList.add(gkdId);
        GkUseData gkdPId = new GkUseData();
        gkdPId.setLinkId(linkId);
        gkdPId.setCodeDesc(GkConstants.GK_DEF_COLUMN.PID.getCodeDesc());
        gkdPId.setNameStr(GkConstants.GK_DEF_COLUMN.PID.getNameDesc());
        gkdPId.setValueStr(pid);
        gkdPId.setTemplateId(templateId);
        gkdPId.setCompanyId(SecurityUtils.getCompanyId());
        gkUseDataList.add(gkdPId);

        for (GkUseDataItemVo itemVo : itemVos) {
            GkUseData gkd = new GkUseData();
            String nameStr = itemVo.getNameStr();
            String valueStr = itemVo.getValueStr();
            String codeDesc = itemVo.getCodeDesc();
            gkd.setLinkId(linkId);
            gkd.setCodeDesc(codeDesc);
            gkd.setNameStr(nameStr);
            gkd.setValueStr(valueStr);
            gkd.setTemplateId(templateId);
            gkd.setCompanyId(SecurityUtils.getCompanyId());
            gkUseDataList.add(gkd);
        }
        this.saveBatch(gkUseDataList);
        return 1;
    }

    /**
     * 修改归口数据
     *
     * @param vo 归口数据
     * @return 结果
     */
    @Override
    public int updateGkUseData(GkUseDataVo vo)
    {
        String linkId = vo.getLinkId();
        String templateId = vo.getTemplateId();

        this.remove(
                Wrappers.<GkUseData>lambdaQuery()
                .eq(GkUseData::getCompanyId,SecurityUtils.getCompanyId())
                .eq(GkUseData::getTemplateId,templateId)
                .eq(GkUseData::getLinkId,linkId)
                .notIn(GkUseData::getCodeDesc,GkConstants.GK_DEF_COLUMN.ID.getCodeDesc(),GkConstants.GK_DEF_COLUMN.PID.getCodeDesc())
        );

        List<GkUseDataItemVo> itemVos = vo.getItemVos();
        List<GkUseData> gkUseDataList = new ArrayList<>();
        for (GkUseDataItemVo itemVo : itemVos) {
            GkUseData gkd = new GkUseData();
            String nameStr = itemVo.getNameStr();
            String valueStr = itemVo.getValueStr();
            String codeDesc = itemVo.getCodeDesc();
            gkd.setLinkId(linkId);
            gkd.setCodeDesc(codeDesc);
            gkd.setNameStr(nameStr);
            gkd.setValueStr(valueStr);
            gkd.setTemplateId(templateId);
            gkd.setCompanyId(SecurityUtils.getCompanyId());
            gkUseDataList.add(gkd);
        }
        this.saveBatch(gkUseDataList);
        return 1;
    }

    /**
     * 批量删除归口数据
     *
     * @param ids 需要删除的归口数据主键
     * @return 结果
     */
    @Override
    public int deleteGkUseDataByIds(String[] ids)
    {
        return gkUseDataMapper.deleteGkUseDataByIds(ids);
    }

    /**
     * 删除归口数据信息
     *
     * @param id 归口数据主键
     * @return 结果
     */
    @Override
    public int deleteGkUseDataById(String id)
    {
        return gkUseDataMapper.deleteGkUseDataById(id);
    }

    @Override
    public List<TreeBo> listtree(String templateId) {
        //
        List<GkUseData> gkUseData = gkUseDataMapper.selectList(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId, SecurityUtils.getCompanyId())
                        .eq(GkUseData::getTemplateId, templateId)
        );
        Map<String, List<GkUseData>> collect = gkUseData.stream().collect(Collectors.groupingBy(GkUseData::getLinkId));
        List<GkUserDataBo> gkUserDataBos = new ArrayList<>();
        Set<Map.Entry<String, List<GkUseData>>> entries = collect.entrySet();
        for (Map.Entry<String, List<GkUseData>> entry : entries) {
            String key = entry.getKey();
            List<GkUseData> value = entry.getValue();
            GkUserDataBo gkUserDataBo = new GkUserDataBo();
            gkUserDataBo.setId(key);
            for (GkUseData gkUseDatum : value) {
                String codeDesc = gkUseDatum.getCodeDesc();
                String valueStr = gkUseDatum.getValueStr();
                Integer orderNum = gkUseDatum.getOrderNum();
                if (GkConstants.GK_DEF_COLUMN.PID.getCodeDesc().equals(codeDesc)) {
                    gkUserDataBo.setPid(valueStr);
                }
                if (GkConstants.GK_DEF_COLUMN.NAME.getCodeDesc().equals(codeDesc)) {
                    gkUserDataBo.setName(valueStr);
                    gkUserDataBo.setOrderNum(orderNum);
                }
            }
            gkUserDataBos.add(gkUserDataBo);
        }
        TreeBo rootBo = new TreeBo();
        rootBo.setId(CommonConstants.DEF_PID);
        rootBo.setName("全部");
        List<TreeBo> convert = TreeBo.convert(gkUserDataBos);
        rootBo.setChildren(convert);
        List<TreeBo> result = new ArrayList<>();
        result.add(rootBo);
        return result;
    }

    @Override
    public List<GkTreeList> listGkTable(String templateId) {
        List<GkUseData> gkUseData = gkUseDataMapper.selectList(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId, SecurityUtils.getCompanyId())
                        .eq(GkUseData::getTemplateId, templateId)
                .orderByAsc(GkUseData::getOrderNum)
        );


        LinkedHashMap<String, List<GkUseData>> collect = new LinkedHashMap<>();
        for (GkUseData gkUseDatum : gkUseData) {
            String linkId = gkUseDatum.getLinkId();
            if(collect.containsKey(linkId)){
                collect.get(linkId).add(gkUseDatum);
            }else {
                List<GkUseData> gkUseDataList = new ArrayList<GkUseData>(1);
                gkUseDataList.add(gkUseDatum);
                collect.put(linkId,gkUseDataList);
            }
        }
//        Map<String, List<GkUseData>> collect = gkUseData.stream().collect(Collectors.groupingBy(GkUseData::getLinkId));

        Set<Map.Entry<String, List<GkUseData>>> entries = collect.entrySet();

        List<GkTreeList> gkTreeLists = new ArrayList<>();

        for (Map.Entry<String, List<GkUseData>> entry : entries) {
            List<GkUseData> value = entry.getValue();

            GkTreeList gkTree = new GkTreeList();
            gkTree.put("linkId",entry.getKey());
            for (GkUseData gkUseDatum : value) {
                String codeDesc = gkUseDatum.getCodeDesc();
                String valueStr = gkUseDatum.getValueStr();
                gkTree.put(codeDesc,valueStr);
            }
            gkTreeLists.add(gkTree);

        }

        ListValueMap<String,GkTreeList> listValueMap = new ListValueMap<>();
        for (GkTreeList gkTreeList : gkTreeLists) {
            String pid = Convert.toStr(gkTreeList.get(GkConstants.GK_DEF_COLUMN.PID.getCodeDesc()));
            listValueMap.putValue(pid,gkTreeList);
        }

        List<GkTreeList> rootList = listValueMap.get(CommonConstants.DEF_PID);

        if(CollUtil.isNotEmpty(rootList)){
            Integer index = 0;
            for (GkTreeList gkTreeList : rootList) {
                index++;
                gkTreeList.put("indexOne",index);
                getGkChildren(listValueMap,gkTreeList,index.toString());
            }
        }

        return rootList;
    }

    @Override
    public List<GkTreeList> listGkTableSimplify(String templateId) {
        List<String> list = new ArrayList<>();
        list.add("GK0001");
        list.add("GK0002");
        list.add("GK0003");

        // 查自己专业
        List<GkUseData> gkUseData = gkUseDataMapper.selectList(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId, SecurityUtils.getCompanyId())
                        .eq(GkUseData::getTemplateId, templateId)
                        .in(GkUseData::getCodeDesc,list)
                        .orderByAsc(GkUseData::getOrderNum)
        );

        LinkedHashMap<String, List<GkUseData>> collect = new LinkedHashMap<>();
        for (GkUseData gkUseDatum : gkUseData) {
            String linkId = gkUseDatum.getLinkId();
            if(collect.containsKey(linkId)){
                collect.get(linkId).add(gkUseDatum);
            }else {
                List<GkUseData> gkUseDataList = new ArrayList<GkUseData>(1);
                gkUseDataList.add(gkUseDatum);
                collect.put(linkId,gkUseDataList);
            }
        }
//        Map<String, List<GkUseData>> collect = gkUseData.stream().collect(Collectors.groupingBy(GkUseData::getLinkId));

        Set<Map.Entry<String, List<GkUseData>>> entries = collect.entrySet();

        List<GkTreeList> gkTreeLists = new ArrayList<>();

        for (Map.Entry<String, List<GkUseData>> entry : entries) {
            List<GkUseData> value = entry.getValue();

            GkTreeList gkTree = new GkTreeList();
            gkTree.put("linkId",entry.getKey());
            for (GkUseData gkUseDatum : value) {
                String codeDesc = gkUseDatum.getCodeDesc();
                String valueStr = gkUseDatum.getValueStr();
                gkTree.put(codeDesc,valueStr);
            }
            gkTreeLists.add(gkTree);

        }

        ListValueMap<String,GkTreeList> listValueMap = new ListValueMap<>();
        for (GkTreeList gkTreeList : gkTreeLists) {
            String pid = Convert.toStr(gkTreeList.get(GkConstants.GK_DEF_COLUMN.PID.getCodeDesc()));
            listValueMap.putValue(pid,gkTreeList);
        }

        List<GkTreeList> rootList = listValueMap.get(CommonConstants.DEF_PID);

        if(CollUtil.isNotEmpty(rootList)){
            Integer index = 0;
            for (GkTreeList gkTreeList : rootList) {
                index++;
                gkTreeList.put("indexOne",index);
                getGkChildren(listValueMap,gkTreeList,index.toString());
            }
        }

        return rootList;

    }

    private void getGkChildren(ListValueMap<String, GkTreeList> listValueMap, GkTreeList root,String index) {
        String id = Convert.toStr(root.get(GkConstants.GK_DEF_COLUMN.ID.getCodeDesc()));
        List<GkTreeList> childrenList = listValueMap.get(id);
        if (CollUtil.isNotEmpty(childrenList)) {
            Integer indexNew = 0;
            root.put("children",childrenList);
            for (GkTreeList gkTreeList : childrenList) {
                indexNew++;
                gkTreeList.put("indexOne",index+"."+indexNew);
                getGkChildren(listValueMap,gkTreeList,index+"."+indexNew);
            }
        }
    }

    @Override
    public Map<String, Object> getInfoObj(String templateId, String id) {

        List<GkUseData> gkUseData = gkUseDataMapper.selectList(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId, SecurityUtils.getCompanyId())
                        .eq(GkUseData::getTemplateId, templateId)
                        .eq(GkUseData::getLinkId,id)
        );
        Map<String, Object> resultMap = new HashMap<>();
        for (GkUseData gkUseDatum : gkUseData) {
            resultMap.put(gkUseDatum.getCodeDesc(),gkUseDatum.getValueStr());
        }
        return resultMap;
    }

    @Override
    @Transactional
    public int deleteGkUseData(String templateId, String id) {
        Long companyId = SecurityUtils.getCompanyId();
        // 查询有没有子
        Long aLong = gkUseDataMapper.selectCount(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId, companyId)
                        .eq(GkUseData::getTemplateId, templateId)
                        .eq(GkUseData::getCodeDesc, GkConstants.GK_DEF_COLUMN.PID.getCodeDesc())
                        .eq(GkUseData::getValueStr, id)
        );
        if (aLong > 0) {
            throw new ServiceException("存在子项无法删除!");
        }
        // 删除关联
        String packagingId = "\"" + id + "\"";

        if (companyId == 1594983326471446562L) {
            long l = System.currentTimeMillis();
            // 如果有一天这块报错,那可能是因为普耐端的表跟归口的表不在一块了
            // 如果是这样的话,那就把下面5句删除就好了
            gkUseDataMapper.delAssetExpenseCategoriesLinkGk("," + packagingId);
            gkUseDataMapper.delAssetExpenseCategoriesLinkGk(packagingId + ",");
            gkUseDataMapper.delAssetExpenseCategoriesLinkGk(packagingId);
            gkUseDataMapper.delAssetGxLinkGkLinkGk(id);
            gkUseDataMapper.delAssetGxLinkGkCategoriesLinkGk(id);
            long l1 = System.currentTimeMillis();
            log.debug(l1 - l +"用时");
        } else {
            // 如果有一天这块报错,那可能是因为客户端的表跟归口的表不在一块了
            // 如果是这样的话,那就把下面5句删除就好了
            gkUseDataMapper.delCusExpenseCategoriesLinkGk("," + packagingId, companyId);
            gkUseDataMapper.delCusExpenseCategoriesLinkGk(packagingId + ",", companyId);
            gkUseDataMapper.delCusExpenseCategoriesLinkGk(packagingId, companyId);
            gkUseDataMapper.delCusGxLinkGkLinkGk(id, companyId);
            gkUseDataMapper.delCusGxLinkGkCategoriesLinkGk(id, companyId);
        }

        return gkUseDataMapper.delete(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId, companyId)
                        .eq(GkUseData::getTemplateId, templateId)
                        .eq(GkUseData::getLinkId, id)
        );
    }

    @Override
    public int insertGkUseDataXy(GkUseDataVo vo) {
        String templateId = vo.getTemplateId();
        String pid = vo.getPid();
        HashMap<String, String> itemVosXy = vo.getItemVosXy();
        List<GkUseData> gkUseDataList = new ArrayList<>();

        List<GkItem> templateColumn = iGkTemplateService.getTemplateColumn(templateId);

        String linkId = IdUtil.simpleUUID();

        // 生成id pid 对象数据
        GkUseData gkdId = new GkUseData();
        gkdId.setId(linkId);
        gkdId.setLinkId(linkId);
        gkdId.setCodeDesc(GkConstants.GK_DEF_COLUMN.ID.getCodeDesc());
        gkdId.setNameStr(GkConstants.GK_DEF_COLUMN.ID.getNameDesc());
        gkdId.setValueStr(linkId);
        gkdId.setTemplateId(templateId);
        gkdId.setCompanyId(SecurityUtils.getCompanyId());
        gkUseDataList.add(gkdId);
        GkUseData gkdPId = new GkUseData();
        gkdPId.setLinkId(linkId);
        gkdPId.setCodeDesc(GkConstants.GK_DEF_COLUMN.PID.getCodeDesc());
        gkdPId.setNameStr(GkConstants.GK_DEF_COLUMN.PID.getNameDesc());
        gkdPId.setValueStr(pid);
        gkdPId.setTemplateId(templateId);
        gkdPId.setCompanyId(SecurityUtils.getCompanyId());
        gkUseDataList.add(gkdPId);

        for (GkItem gkItem : templateColumn) {
            GkUseData gkd = new GkUseData();
            gkd.setLinkId(linkId);
            gkd.setCodeDesc(gkItem.getCodeDesc());
            gkd.setNameStr(gkItem.getNameDesc());
            gkd.setValueStr(itemVosXy.get(gkItem.getCodeDesc()));
            gkd.setTemplateId(templateId);
            gkd.setCompanyId(SecurityUtils.getCompanyId());
            gkUseDataList.add(gkd);
        }
        this.saveBatch(gkUseDataList);
        return 1;
    }

    @Override
    public int updateGkUseDataXy(GkUseDataVo vo) {
        String linkId = vo.getLinkId();
        String templateId = vo.getTemplateId();
        HashMap<String, String> itemVosXy = vo.getItemVosXy();

        this.remove(
                Wrappers.<GkUseData>lambdaQuery()
                        .eq(GkUseData::getCompanyId,SecurityUtils.getCompanyId())
                        .eq(GkUseData::getTemplateId,templateId)
                        .eq(GkUseData::getLinkId,linkId)
                        .notIn(GkUseData::getCodeDesc,GkConstants.GK_DEF_COLUMN.ID.getCodeDesc(),GkConstants.GK_DEF_COLUMN.PID.getCodeDesc())
        );

        List<GkItem> templateColumn = iGkTemplateService.getTemplateColumn(templateId);
        List<GkUseData> gkUseDataList = new ArrayList<>();
        for (GkItem gkItem : templateColumn) {
            GkUseData gkd = new GkUseData();
            gkd.setLinkId(linkId);
            gkd.setCodeDesc(gkItem.getCodeDesc());
            gkd.setNameStr(gkItem.getNameDesc());
            gkd.setValueStr(itemVosXy.get(gkItem.getCodeDesc()));
            gkd.setTemplateId(templateId);
            gkd.setCompanyId(SecurityUtils.getCompanyId());
            gkUseDataList.add(gkd);
        }
        this.saveBatch(gkUseDataList);
        return 1;
    }

    @Override
    public int moveDataXY(String id, String dropId) {
        Long companyId = SecurityUtils.getCompanyId();
//        if (!StringUtils.equals(dropId,"0") && gkUseDataMapper.checkDataCY(companyId, id, dropId) != 0) {
//            throw new RuntimeException("错误移动");
//        }
        gkUseDataMapper.moveDataXY(companyId,id,dropId);
        return 200;
    }
}
